`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 05/03/2021 10:12:52 AM
// Design Name: 
// Module Name: counter_led
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

`include "e203_defines.v"

module counter_led(
    input clk,
    input rst_n,
    output [1:0] led
    );
    
    reg [25:0] pre_cnt;
    
    //PLL, product sys_clk
    //    
    wire sys_clk;
    
    CLK_PLL pll(
        .clk_out1(sys_clk), //output clkout
        .clk_in1(clk) //input clkin
    );
    
    reg [3:0] addr;
    wire [31:0] instruction;
    
    //ROM part
    //addressed from pc_value
    //provide instruction            
    I_ROM data_rom(
        .clka(sys_clk), 
        .ena(1), 
        .addra(pc_value[5:2]),
        .douta(instruction) 
    );
   
    //product core_clk
    //by prescale sys_clk
    wire core_clk = addr[0];            
    always@(posedge sys_clk or negedge rst_n) begin
          if (~rst_n) begin
            pre_cnt<=0;
            addr<=0;
          end
          else begin
            pre_cnt<=pre_cnt+1;
            if (pre_cnt==0) begin
              addr<=addr+1;
            end
          end
        end    

wire [`E203_DECINFO_WIDTH-1:0]  dec_info;
wire dec_rv32;
wire dec_jal;

wire dec_rs1x0;
wire dec_rs2x0;
wire dec_rs1en;
wire dec_rs2en;
wire dec_rdwen;
wire [4:0] dec_rs1idx;
wire [4:0] dec_rs2idx;
wire [4:0] dec_rdidx;
wire [`E203_XLEN-1:0] dec_imm;


  //decoder
  e203_exu_decode u_e203_exu_decode(
  .i_instr(instruction),
  .i_pc(`E203_PC_SIZE'b0),
  .i_prdt_taken(1'b0), 
  .i_muldiv_b2b(1'b0), 
  .i_misalgn (1'b0),
  .i_buserr  (1'b0),
  .dbg_mode  (1'b0),
  .dec_rv32(dec_rv32),
  .dec_rs1x0 (dec_rs1x0),
  .dec_rs2x0 (dec_rs2x0),
  .dec_rs1en (dec_rs1en),
  .dec_rs2en (dec_rs2en),
  .dec_rdwen (dec_rdwen),
  .dec_rs1idx(dec_rs1idx),
  .dec_rs2idx(dec_rs2idx),
  .dec_rdidx (dec_rdidx),
  .dec_imm(dec_imm),
  .dec_jal (dec_jal ),
  .dec_info  (dec_info )
  );

  //Program Counter
  //  
  wire [31:0] pc_value;
  wire [31:0] pc_r;
  wire [31:0] pc_next;

  //PC as 32 D flip-flops
  //triggered by core_clk
  sirv_gnrl_dfflr #(32) pc_dfflr (1'b1, pc_next, pc_r, core_clk, rst_n);
  assign pc_value = pc_r;  

  //next pc value could be:
  //jal: pc = pc + imm;
  //normal: pc = pc + 4
  wire [31:0] adder_pc_add_four = pc_r + 32'd4;
  wire [31:0] adder_pc_add_imm = pc_r + dec_imm;
  assign pc_next = dec_jal ? adder_pc_add_imm : adder_pc_add_four;

  //

  //ALU
  
  wire[31:0] alu_data_a;
  wire[31:0] alu_data_b;
  wire alu_sub_flag;
  wire alu_add_flag;
  wire alu_enable;
  wire [31:0] rf_rd_data_alu_result;


    //alu
    zh_exec_alu_v02 m_zh_exec_alu(
        .i_alu_data_a(alu_data_a),
        .i_alu_data_b(alu_data_b),
        .i_alu_add_flag(alu_add_flag),
        .i_alu_sub_flag(alu_sub_flag),
        .i_alu_enable(alu_enable),
        .alu_result(rf_rd_data_alu_result)
    );

  assign alu_enable = (dec_info[`E203_DECINFO_GRP] == `E203_DECINFO_GRP_ALU);

assign alu_data_a = rf_rs1data;

assign alu_data_b = dec_info[`E203_DECINFO_ALU_OP2IMM] ? dec_imm : rf_rs2data;
  assign alu_add_flag = dec_info[`E203_DECINFO_ALU_ADD];
  assign alu_sub_flag = dec_info[`E203_DECINFO_ALU_SUB];
  
  
  
  
  //Register File block
  wire[4:0] rf_rs1idx;
  wire[4:0] rf_rs2idx;
  wire[31:0] rf_rs1data;
  wire[31:0] rf_rs2data;
  wire[4:0] rf_rdidx;
  wire rf_rdwen;
  wire[31:0] rf_rd_data;
  wire[31:0] gpio1out;
    
    //register file module
  zh_regfile_v01 m_zh_regfile(
      .rst_n(rst_n),
      .core_clk(core_clk),

      .i_rf_rs1idx(rf_rs1idx),
      .i_rf_rs2idx(rf_rs2idx),
      .rf_rs1data(rf_rs1data),
      .rf_rs2data(rf_rs2data),
      .i_rf_rdidx(rf_rdidx),
      .i_rf_rdwen(rf_rdwen),
      .i_rf_rd_data(rf_rd_data),
      .gpio1out(gpio1out)
  );

  //retrieve reg data
  assign rf_rs1idx={5{dec_rs1en   }} & dec_rs1idx;
  assign rf_rs2idx={5{dec_rs2en   }} & dec_rs2idx;  

  //write back result
  assign rf_rdidx=dec_rdidx;
  assign rf_rdwen=dec_rdwen;

  assign rf_rd_data =  alu_enable ? rf_rd_data_alu_result : 32'b0;

  //led output
assign led[1] = ~gpio1out[1];
assign led[0] = ~gpio1out[0];

endmodule
